import logging
from device import Switch 
from owfs import Owfs

logger = logging.getLogger(__name__)



class Alarm:
    _none = 0
    _pullUp = 1
    _alarmMasked = 2

    def __init__(self):
        self.bitcnt = {}   #addressed by byte alarm
        self.lastAction = Alarm._none
        
    def inc(self, bit):
        if not bit in self.bitcnt:
            self.bitcnt[bit] = 1
        else:
            self.bitcnt[bit] += 1

class DisturbanceFilter:
    "DisturbanceFilter.checkAll() shall be trigged 10x per second"

    def __init__(self, pollInt):
        self.alarms = {}
        self.pollInt = pollInt
        self.pollcnt = 0

    def addDevice(self, addr):
        if not addr in self.alarms:
            self.alarms[addr] = Alarm()
            logger.debug("added alarm dev %s" % addr)
        return self.alarms[addr]

    def removeDevice(self, addr):
        if addr in self.alarms:
            del self.alarms[addr]

    def alarm(self, addr, bit):
        #TODO: separate bits
        try:
            self.alarms[addr].inc(bit)
            logger.debug("filter %s count: %d" % (addr, self.alarms[addr].bitcnt[bit])) 
        except KeyError:
            self.addDevice(addr).inc(bit)


    def bit(self, mask):
        if mask == 0:
            raise ValueError
        b = 1
        i = 0
        while (b << i) != mask:
            i += 1
        return i

        
    def tryFilter(self, addr, mask):
        owfs = Owfs()
        #2408
        #mask alarm bit
        alarm = self.alarms[addr]
        if alarm.lastAction == Alarm._none:
            logger.debug("filter %s pull up input %d" % (addr, self.bit(mask)))
            owfs.write(addr + "/PIO." + str(self.bit(mask)), "1")
            alarm.lastAction = Alarm._pullUp
        elif alarm.lastAction == Alarm._pullUp:
            a = list(owfs.read(addr + "/set_alarm"))
            for bit in range(0, 7):
                if mask & (1 << bit):
                    a[-(bit + 1)] = '0'
            set_alarm = ''.join(a)
            logger.info("Alarm filter %s: set_alarm: %s" % (addr, set_alarm))
            owfs.write(addr + "/set_alarm", set_alarm)
        

        

    def checkAll(self):
        self.pollcnt += 1
        if self.pollcnt > (1 / self.pollInt):
            logger.debug("checkAll")
            for a in self.alarms:
                for bit in self.alarms[a].bitcnt:
                    if self.alarms[a].bitcnt[bit] >= 10:
                        logger.info("Detected disturbance %s byte %02x" % (a, bit))
                        self.tryFilter(a, bit)
                    self.alarms[a].bitcnt[bit] = 0
            self.pollcnt = 0


